﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;

namespace Kaleta.Xna.Animators
{
    /// <summary>
    /// Provides an iterator behavior for linear gradient. 
    /// </summary>
    public class GradientAnimator
    {
        private Color _currentColor;
        public Color CurrentColor { get { return _currentColor; } private set { _currentColor = value; } }

        private float _iterator;
        public float Iterator
        {
            get { return this._iterator; }
            set
            {
                if (value == this._iterator) return;

                if (value < 0 || value > 1)
                    throw new ArgumentException("Iterator value must be within range 0 and 1");

                this._iterator = value;

                GradientStop stop1, stop2;
                float colorrange;
                float R, G, B, A;

                //find out in which gradient stop the color belongs to:
                for (int i = 0; i < gradientStops.Count - 1; i++)
                {
                    stop1 = gradientStops[i];
                    stop2 = gradientStops[i + 1];

                    if (stop1.Offset <= value && value <= stop2.Offset)
                    {
                        colorrange = (value - stop1.Offset) / (stop2.Offset - stop1.Offset);
                        R = stop2.Color.R - stop1.Color.R;
                        G = stop2.Color.G - stop1.Color.G;
                        B = stop2.Color.B - stop1.Color.B;
                        A = stop2.Color.A - stop1.Color.A;

                        _currentColor.R = (byte) (R * colorrange + stop1.Color.R);
                        _currentColor.G = (byte) (G * colorrange + stop1.Color.G);
                        _currentColor.B = (byte) (B * colorrange + stop1.Color.B);
                        _currentColor.A = (byte) (A * colorrange + stop1.Color.A);


                        return;
                    }

                }

            }
        }

        public GradientAnimator(params GradientStop[] stops)
        {
            if (stops.Length < 2)
                throw new ArgumentException("There must be at least two gradient stops");

            foreach (var stop in stops)
            {
                if (stop.Offset > 1 || stop.Offset < 0)
                    throw new ArgumentException("The gradient offset must be within 0 and 1 range");

                gradientStops.Add(stop);
            }

            gradientStops.Sort(new GradientStopComparer());
            if (gradientStops[0].Offset != 0)
                throw new ArgumentException("The first gradient stop must have an offset of 0");


            this.CurrentColor = gradientStops[0].Color;
            this.Iterator = 0;
        }

        private List<GradientStop> gradientStops = new List<GradientStop>();
    }
    public class GradientStop
    {
        public Color Color { get; private set; }
        public float Offset { get; private set; }
        public GradientStop(Color color, float offset)
        {
            this.Color = color;
            this.Offset = offset;
        }
    }

    public class GradientStopComparer : IComparer<GradientStop>
    {
        public int Compare(GradientStop stop1, GradientStop stop2)
        {
            if (stop1.Offset < stop2.Offset)
                return -1;
            if (stop1.Offset > stop2.Offset)
                return 1;

            return 0;
        }
    }

    //public class Color
    //{
    //    public float R { get; set; }
    //    public float G { get; set; }
    //    public float B { get; set; }
    //    public float A { get; set; }

    //    public Color(float r, float g, float b, float a)
    //    {
    //        R = r; G = g; B = b; A = a;
    //    }

    //    public override string ToString()
    //    {
    //        return "(" + R + " , " + G + " , " + B + ")";
    //    }
    //}
}
